package com.gestionabsences.form;

import com.gestionabsences.beans.MapMatters;
import com.gestionabsences.beans.ResultRequest;
import com.gestionabsences.config.DAOFactory;
import com.gestionabsences.database.ToolsRequest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

/**
 *
 * @author matt
 */
public class FormTeacherReport {
    public static final String CHAMP_MATIERE = "matiere";
    public static final String CHAMP_SEANCE = "seance";
    public static final String CHAMP_TYPE_SEANCE = "type_seance";
    public static final String CHAMP_ERREUR = "erreur";
    public static final String CHAMP_MATIERE_SPECIFIE = "former_matiere";
    public static final String CHAMP_SEANCE_SPECIFIE = "former_seance";
    public static final String CHAMP_TYPE_SEANCE_SPECIFIE = "former_type_seance";
    public static final String CHAMP_STUDENT_CHECKED = "student";
    public static final String CHAMP_NOMBRE_ETUDIANTS = "nombreEtudiants";
    
    private String formerValMatiere;
    private String formerValSeance;
    private String formerValTypeSeance;
    
    private String nombreEtudiants;
    
    private String resultatInsertion;
    
    private Map<String, String> erreurs;
    private MapMatters listeMatieres;
    private DAOFactory dao;
    private String immatriculation;
    
    public FormTeacherReport(DAOFactory dao, MapMatters listMatieres, String immatriculation) {
	this.erreurs = new HashMap<String, String>();
	this.listeMatieres = listMatieres;
	this.dao = dao;
	this.immatriculation = immatriculation;
    }
    
    public ResultRequest recuperationListeEtudiants( HttpServletRequest request ) {
	
	String id_matiere = getValeurChamp( request, CHAMP_MATIERE_SPECIFIE );
	String seance = getValeurChamp( request, CHAMP_SEANCE);
	String type = getValeurChamp( request, CHAMP_TYPE_SEANCE);
	
	try {
            validationTypeSeance( type );
        } catch ( Exception e ) {
            setErreur( CHAMP_TYPE_SEANCE, e.getMessage() );
        }
	
	/* Créer la validation pour les  séances également, plus tard si le temps */
	
	try {
            validationMatiere( id_matiere );
        } catch ( Exception e ) {
            setErreur( CHAMP_MATIERE, e.getMessage() );
        }
	
	ResultRequest res = null;
	
	if( erreurs.isEmpty() ) {
	    this.formerValMatiere = id_matiere;
	    this.formerValSeance = seance;
	    this.formerValTypeSeance = type;
	    
	    res = createListStudentsFromArgs(id_matiere);
	    this.nombreEtudiants = "" + res.getTuples().size();
	    
	    if(res != null) {
		if( !res.isResultatPresent() ) {
		    res = null;
		}
	    }
	}
	
	return res;
    }
    
    private ResultRequest createListStudentsFromArgs(String id_matiere) {
	
	ArrayList<String> tabColonnes = new ArrayList<String>();
	tabColonnes.add("ine");
	tabColonnes.add("nom");
	tabColonnes.add("prenom");
	tabColonnes.add("affectation");
	
	String sql_req = "SELECT * FROM getListStudents(" + id_matiere + ")";
	
	Connection connexion = null;
	ResultRequest res = null;
	
	try {
	    connexion = dao.getConnection();
	    
	    PreparedStatement preparedStatement = null;
	    ResultSet resultSet = null;
	
	    try {
		preparedStatement = ToolsRequest.prepareRequest( connexion, sql_req, false);
		//setErreur( CHAMP_ERREUR, preparedStatement.toString() );
		System.out.println("query :  " + preparedStatement.toString());
		
		resultSet = preparedStatement.executeQuery();
		
		res = new ResultRequest(resultSet, tabColonnes.toArray());
				
	    } catch(Exception e) {
		setErreur( CHAMP_ERREUR, preparedStatement.toString() + " => " + e.getMessage() );
	    }
	    finally {
		ToolsRequest.close(preparedStatement, resultSet);
	    }
	} catch (SQLException e) {
	    setErreur( CHAMP_ERREUR, e.getMessage() );
	}
	finally {
	    ToolsRequest.close(connexion);
	}
	
	return res;
    }
    
    public ResultRequest recuperationListeSeances( HttpServletRequest request ) {
	
	String id_matiere = getValeurChamp( request, CHAMP_MATIERE );
	
	try {
            validationMatiere( id_matiere );
        } catch ( Exception e ) {
            setErreur( CHAMP_MATIERE, e.getMessage() );
        }
	
	ResultRequest res = null;
	
	if( erreurs.isEmpty() ) {
	    formerValMatiere = id_matiere;
	    
	    res = createListSeancesFromArgs(id_matiere, this.immatriculation);
	    if(res != null) {
		if( !res.isResultatPresent() ) {
		    res = null;
		}
	    }
	}
	
	return res;
    }
    
    private ResultRequest createListSeancesFromArgs(String id_matiere, String immatriculation) {
	
	ArrayList<String> tabColonnes = new ArrayList<String>();
	tabColonnes.add("id_seance");
	tabColonnes.add("salle");
	tabColonnes.add("isa");
	tabColonnes.add("heure");
	
	String sql_req = "SELECT * FROM getListSeances(" + id_matiere + ", '" + immatriculation + "')";
	
	Connection connexion = null;
	ResultRequest res = null;
	
	try {
	    connexion = dao.getConnection();
	    
	    PreparedStatement preparedStatement = null;
	    ResultSet resultSet = null;
	
	    try {
		preparedStatement = ToolsRequest.prepareRequest( connexion, sql_req, false);
		//setErreur( CHAMP_ERREUR, preparedStatement.toString() );
		System.out.println("query :  " + preparedStatement.toString());
		
		resultSet = preparedStatement.executeQuery();
		
		res = new ResultRequest(resultSet, tabColonnes.toArray());
				
	    } catch(Exception e) {
		setErreur( CHAMP_ERREUR, preparedStatement.toString() + " => " + e.getMessage() );
	    }
	    finally {
		ToolsRequest.close(preparedStatement, resultSet);
	    }
	} catch (SQLException e) {
	    setErreur( CHAMP_ERREUR, e.getMessage() );
	}
	finally {
	    ToolsRequest.close(connexion);
	}
	
	return res;
    }
    
    public boolean checkAsAbsent(HttpServletRequest request) {	
	boolean absentsInserted;
	
	String id_matiere = getValeurChamp(request, CHAMP_MATIERE_SPECIFIE);
	String seance = getValeurChamp(request, CHAMP_SEANCE_SPECIFIE);
	String typeSeance = getValeurChamp(request, CHAMP_TYPE_SEANCE_SPECIFIE);
	String nombreEtudiants = getValeurChamp(request, CHAMP_NOMBRE_ETUDIANTS);
	
	ArrayList<String> listeAbsents = new ArrayList<String>();
	int nbrTotalEtudiants = Integer.parseInt(nombreEtudiants);
	
	String studentINE = getValeurChamp(request, CHAMP_STUDENT_CHECKED + 0);
	for(int i=1; i < nbrTotalEtudiants; i++) {
	    System.out.println("student à déclarer absent : " + studentINE);
	    if(studentINE != null) {
		listeAbsents.add(studentINE);
	    }
	    studentINE = getValeurChamp(request, CHAMP_STUDENT_CHECKED + i);
	}
	
	try {
            validationTypeSeance( typeSeance );
	    System.out.println("type séance validée.");
        } catch ( Exception e ) {
            setErreur( CHAMP_TYPE_SEANCE, e.getMessage() );
        }
	
	try {
	    validationListAbsents(listeAbsents);
	    System.out.println("Liste d'absents validée.");
	} catch (Exception e ) {
            setErreur( CHAMP_STUDENT_CHECKED, e.getMessage() );
        }
	
	/* Créer la validation pour les  séances également, plus tard si le temps */
	
	try {
            validationMatiere( id_matiere );
	    System.out.println("matière validée.");
        } catch ( Exception e ) {
            setErreur( CHAMP_MATIERE, e.getMessage() );
        }
	
	if (erreurs.isEmpty() && !listeAbsents.isEmpty() ) {
	    formerValMatiere = id_matiere;

	    absentsInserted = insertionAbsents(listeAbsents, id_matiere, seance, typeSeance);
	    this.resultatInsertion = (absentsInserted) ? "Les absents ont été insérés dans la table d'absences." : "Les absents n'ont pu être tous insérés dans la table d'absences.";
	} else {
	    System.out.println( erreurs.toString() );
	    System.out.println( listeAbsents.toString() );
	    System.out.println("Aucune insertion a été effectué.");
	    absentsInserted = false;
	    this.resultatInsertion = "Aucune insertion a été effectué.";
	}
	
	return absentsInserted;
    }
    
    private boolean insertionAbsents( ArrayList<String> listeAbsents, String matiere, String seance, String typeSeance ) {
	
	Iterator it = listeAbsents.iterator();
	String sql_req = "SELECT addAbsent(" + seance + ", " + matiere + ", CAST(? AS Type_Seance), ?, null, 0);";
	
	Connection connexion = null;

	try {
	    connexion = dao.getConnection();

	    PreparedStatement preparedStatement = null;
	    ResultSet resultSet = null;

	    try {
		while ( it.hasNext() ) {		    
		    preparedStatement = ToolsRequest.prepareRequest(connexion, sql_req, false, typeSeance, it.next());
		    System.out.println("query :  " + preparedStatement.toString());
		    preparedStatement.executeQuery();
		}
	    } catch (Exception e) {
		setErreur(CHAMP_ERREUR, preparedStatement.toString() + " => " + e.getMessage());
	    } finally {
		ToolsRequest.close(preparedStatement, resultSet);
	    }
	} catch (SQLException e) {
	    setErreur(CHAMP_ERREUR, e.getMessage());
	} finally {
	    ToolsRequest.close(connexion);
	}

	if( this.erreurs.isEmpty() ) {
	    return true;
	} else {
	    return false;
	} 
    }
    
    private void validationListAbsents( ArrayList<String> listeAbsents ) {
	boolean allExists = true;
	
	if( !listeAbsents.isEmpty() ) {
	    Iterator it = listeAbsents.iterator();
	    
	    String sql_req = "SELECT E.ine FROM Etudiant E WHERE E.ine = ?;";
	
	    Connection connexion = null;
	    ResultRequest res = null;
	
	    try {
		connexion = dao.getConnection();

		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;

		try {
		    while ( it.hasNext() && allExists ) {
			preparedStatement = ToolsRequest.prepareRequest( connexion, sql_req, false, it.next() );
			System.out.println("query :  " + preparedStatement.toString());
			resultSet = preparedStatement.executeQuery();
			
			if( !resultSet.next() ) {
			    allExists = false;
			}
		    }
		} catch (Exception e) {
		    setErreur(CHAMP_ERREUR, preparedStatement.toString() + " => " + e.getMessage());
		} finally {
		    ToolsRequest.close(preparedStatement, resultSet);
		}
	    } catch (SQLException e) {
		setErreur(CHAMP_ERREUR, e.getMessage());
	    } finally {
		ToolsRequest.close(connexion);
	    }
	}
	
	if( !allExists ) {
	    setErreur(CHAMP_STUDENT_CHECKED, "Un des étudiants spécifiés n'existent pas");
	}
    }
    
    private void validationMatiere( String idMatiere ) throws Exception {
	if (idMatiere != null) {
	    if (!this.listeMatieres.containsKey(idMatiere)) {
		throw new Exception("La matière spécifié n'existe pas ou ne fait pas parti de vos cours.");
	    }
	} else {
	    throw new Exception("Une matière doit être spécifiée pour faire la recherche.");
	}
    }
    
    private void validationTypeSeance(String typeSeance) throws Exception {
	final String TYPE1 = "COURS";
	final String TYPE2 = "TPS";
	final String TYPE3 = "TDS";
	
	if( typeSeance.compareTo(TYPE1) != 0 && typeSeance.compareTo(TYPE2) != 0 && typeSeance.compareTo(TYPE3) != 0 ) {
	    throw new Exception( "Le type '" + typeSeance + "' n'existe pas." );
	}
    }
    
    public String getResultatInsertion() {
	return this.resultatInsertion;
    }
    
    public String getFormerValMatiere() {
	return this.formerValMatiere;
    }
    
    public String getFormerValSeance() {
	return this.formerValSeance;
    }
    
    public String getFormerValTypeSeance () {
	return this.formerValTypeSeance;
    }
    
    public String getNombreEtudiants() {
	return this.nombreEtudiants;
    }
    
    public Map<String, String> getErreurs() {
        return erreurs;
    }
    
    private void setErreur( String champ, String message ) {
	String previous = erreurs.get(champ);
	if(previous != null) {
	    erreurs.put( champ, previous + message );
	}
	else {
	    erreurs.put( champ, message );
	}
	
    }
    
    private static String getValeurChamp( HttpServletRequest request, String nomChamp ) {
        String valeur = request.getParameter( nomChamp );
        if ( valeur == null || valeur.trim().length() == 0 ) {
            return null;
        } else {
            return valeur;
        }
    }
}
